home *** CD-ROM | disk | FTP | other *** search
/ QRZ! Ham Radio 8 / QRZ Ham Radio Callsign Database - Volume 8.iso / mac / files / t_sys5 / unixcpio.gz / unixnet.cpio / mbuf.c < prev    next >
C/C++ Source or Header  |  1994-07-11  |  9KB  |  448 lines

  1. /* Primitive mbuf allocate/free routines */
  2.  
  3. #include "global.h"
  4. #include "mbuf.h"
  5. #ifdef    UNIX
  6. #include <memory.h>
  7. #endif
  8.  
  9. /* Allocate mbuf with associated buffer of 'size' bytes */
  10. struct mbuf *
  11. alloc_mbuf(size)
  12. register int16 size;
  13. {
  14.     register struct mbuf *bp;
  15.  
  16.     if((bp = (struct mbuf *)malloc((unsigned)(size + sizeof(struct mbuf)))) == NULLBUF)
  17.         return NULLBUF;
  18.     bp->next = bp->anext = NULLBUF;
  19.     if(size != 0){
  20.         bp->data = (char *)(bp + 1);
  21.     } else {
  22.         bp->data = NULLCHAR;
  23.     }
  24.     bp->size = size;
  25.     bp->cnt = 0;
  26.     return bp;
  27. }
  28.  
  29. /* Free all resources associated with mbuf
  30.  * Return pointer to next mbuf in packet chain
  31.  */
  32. struct mbuf *
  33. free_mbuf(bp)
  34. register struct mbuf *bp;
  35. {
  36.     register struct mbuf *bp1 = NULLBUF;
  37.  
  38.     if(bp != NULLBUF){
  39.         bp1 = bp->next;
  40.         bp->next = NULLBUF;    /* detect attempts to use */
  41.         bp->data = NULLCHAR;    /* a freed mbuf */
  42.         free((char *)bp);
  43.     }
  44.     return bp1;
  45. }
  46.  
  47. /* Free packet (a chain of mbufs). Return pointer to next packet on queue,
  48.  * if any
  49.  */
  50. struct mbuf *
  51. free_p(bp)
  52. register struct mbuf *bp;
  53. {
  54.     struct mbuf *abp;
  55.  
  56.     if(bp == NULLBUF)
  57.         return NULLBUF;
  58.     abp = bp->anext;
  59.     while(bp != NULLBUF)
  60.         bp = free_mbuf(bp);
  61.     return abp;
  62. }        
  63. /* Free entire queue of packets (of mbufs) */
  64. free_q(q)
  65. struct mbuf **q;
  66. {
  67.     register struct mbuf *bp;
  68.  
  69.     while((bp = dequeue(q)) != NULLBUF)
  70.         free_p(bp);
  71. }
  72.  
  73. /* Count up the total number of bytes in an mbuf */
  74. int16
  75. len_mbuf(bp)
  76. register struct mbuf *bp;
  77. {
  78.     int cnt;
  79.  
  80.     cnt = 0;
  81.     while(bp != NULLBUF){
  82.         cnt += bp->cnt;
  83.         bp = bp->next;
  84.     }
  85.     return cnt;
  86. }
  87. /* Count up the number of packets in a queue */
  88. int16
  89. len_q(bp)
  90. register struct mbuf *bp;
  91. {
  92.     register int cnt;
  93.  
  94.     for(cnt=0;bp != NULLBUF;cnt++,bp = bp->anext)
  95.         ;
  96.     return cnt;
  97. }
  98. /* Trim mbuf to specified length by lopping off end */
  99. trim_mbuf(bpp,length)
  100. struct mbuf **bpp;
  101. int16 length;
  102. {
  103.     register int16 tot = 0;
  104.     register struct mbuf *bp;
  105.  
  106.     if(bpp == NULLBUFP || *bpp == NULLBUF)
  107.         return;    /* Nothing to trim */
  108.  
  109.     if(length == 0){
  110.         /* Toss the whole thing */
  111.         free_p(*bpp);
  112.         *bpp = NULLBUF;
  113.         return;
  114.     }
  115.     /* Find the point at which to trim. If length is greater than
  116.      * the packet, we'll just fall through without doing anything
  117.      */
  118.     for( bp = *bpp; bp != NULLBUF; bp = bp->next){
  119.         if(tot + bp->cnt < length){
  120.             tot += bp->cnt;
  121.         } else {
  122.             /* Cut here */
  123.             bp->cnt = length - tot;
  124.             free_p(bp->next);
  125.             bp->next = NULLBUF;
  126.             break;
  127.         }
  128.     }
  129. }
  130. /* Duplicate/enqueue/dequeue operations based on mbufs */
  131.  
  132. /* Duplicate first 'cnt' bytes of packet starting at 'offset'.
  133.  * This is done without copying data; only the headers are duplicated,
  134.  * but without data segments of their own. The pointers are set up to
  135.  * share the data segments of the original copy. The return pointer is
  136.  * passed back through the first argument, and the return value is the
  137.  * number of bytes actually duplicated.
  138.  */
  139. int16
  140. dup_p(hp,bp,offset,cnt)
  141. struct mbuf **hp;
  142. register struct mbuf *bp;
  143. register int16 offset;
  144. register int16 cnt;
  145. {
  146.     register struct mbuf *cp;
  147.     int16 tot;
  148.  
  149.     if(cnt == 0 || bp == NULLBUF || hp == NULLBUFP){
  150.         if(hp != NULLBUFP)
  151.             *hp = NULLBUF;
  152.         return 0;
  153.     }
  154.     if((*hp = cp = alloc_mbuf(0)) == NULLBUF){
  155.         return 0;
  156.     }
  157.     /* Skip over leading mbufs that are smaller than the offset */
  158.     while(bp != NULLBUF && bp->cnt <= offset){
  159.         offset -= bp->cnt;
  160.         bp = bp->next;
  161.     }
  162.     if(bp == NULLBUF){
  163.         free_mbuf(cp);
  164.         *hp = NULLBUF;
  165.         return 0;    /* Offset was too big */
  166.     }
  167.     tot = 0;
  168.     for(;;){
  169.         cp->data = bp->data + offset;
  170.         cp->cnt = min(cnt,bp->cnt - offset);
  171.         offset = 0;
  172.         cnt -= cp->cnt;
  173.         tot += cp->cnt;
  174.         bp = bp->next;
  175.         if(cnt == 0 || bp == NULLBUF || (cp->next = alloc_mbuf(0)) == NULLBUF)
  176.             break;
  177.         cp = cp->next;
  178.     }
  179.     return tot;
  180. }
  181. /* Copy first 'cnt' bytes of packet into a new, single mbuf */
  182. struct mbuf *
  183. copy_p(bp,cnt)
  184. register struct mbuf *bp;
  185. register int16 cnt;
  186. {
  187.     register struct mbuf *cp;
  188.     register char *wp;
  189.     register int16 n;
  190.  
  191.     if(bp == NULLBUF || cnt == 0 || (cp = alloc_mbuf(cnt)) == NULLBUF)
  192.         return NULLBUF;
  193.     wp = cp->data;
  194.     while(cnt != 0 && bp != NULLBUF){
  195.         n = min(cnt,bp->cnt);
  196.         memcpy(wp,bp->data,(int)n);
  197.         wp += n;
  198.         cp->cnt += n;
  199.         cnt -= n;
  200.         bp = bp->next;
  201.     }
  202.     return cp;
  203. }
  204. /* Copy and delete "cnt" bytes from beginning of packet. Return number of
  205.  * bytes actually pulled off
  206.  */
  207. int16
  208. pullup(bph,buf,cnt)
  209. struct mbuf **bph;
  210. char *buf;
  211. int16 cnt;
  212. {
  213.     register struct mbuf *bp;
  214.     int16 n,tot;
  215.  
  216.     tot = 0;
  217.     if(bph == NULLBUFP)
  218.         return 0;
  219.     while(*bph != NULLBUF && cnt != 0){
  220.         bp = *bph;
  221.         n = min(cnt,bp->cnt);
  222.         if(buf != NULLCHAR && n != 0){
  223.             memcpy(buf,bp->data,(int)n);
  224.             buf += n;
  225.         }
  226.         tot += n;
  227.         cnt -= n;
  228.         bp->data += n;
  229.         bp->cnt -= n;        
  230.         if(bp->cnt == 0){
  231.             *bph = free_mbuf(bp);
  232.         }
  233.     }
  234.     return tot;
  235. }
  236. /* Append mbuf to end of mbuf chain */
  237. void
  238. append(bph,bp)
  239. struct mbuf **bph;
  240. struct mbuf *bp;
  241. {
  242.     register struct mbuf *p;
  243.  
  244.     if(bph == NULLBUFP || bp == NULLBUF)
  245.         return;
  246.     if(*bph == NULLBUF){
  247.         /* First one on chain */
  248.         *bph = bp;
  249.     } else {
  250.         for(p = *bph ; p->next != NULLBUF ; p = p->next)
  251.             ;
  252.         p->next = bp;
  253.     }
  254. }
  255. /* Insert specified amount of contiguous new space at the beginning of an
  256.  * mbuf chain. If enough space is available in the first mbuf, no new space
  257.  * is allocated. Otherwise a mbuf of the appropriate size is allocated and
  258.  * tacked on the front of the chain.
  259.  *
  260.  * This operation is the logical inverse of pullup(), hence the name.
  261.  */
  262. struct mbuf *
  263. pushdown(bp,size)
  264. register struct mbuf *bp;
  265. int16 size;
  266. {
  267.     register struct mbuf *nbp;
  268.  
  269.     /* Check that bp is real and that there's data space associated with
  270.      * this buffer (i.e., this is not a buffer from dup_p) before
  271.      * checking to see if there's enough space at its front
  272.      */
  273.     if(bp != NULLBUF && bp->size != 0 && bp->data - (char *)(bp+1) >= size){
  274.         /* No need to alloc new mbuf, just adjust this one */
  275.         bp->data -= size;
  276.         bp->cnt += size;
  277.     } else {
  278.         if((nbp = alloc_mbuf(size)) != NULLBUF){
  279.             nbp->next = bp;
  280.             nbp->cnt = size;
  281.             bp = nbp;
  282.         } else {
  283.             bp = NULLBUF;
  284.         }
  285.     }
  286.     return bp;
  287. }
  288. /* Append packet to end of packet queue */
  289. void
  290. enqueue(q,bp)
  291. struct mbuf **q;
  292. struct mbuf *bp;
  293. {
  294.     register struct mbuf *p;
  295.     char i_state;
  296.  
  297.     if(q == NULLBUFP || bp == NULLBUF)
  298.         return;
  299.     i_state = disable();
  300.     if(*q == NULLBUF){
  301.         /* List is empty, stick at front */
  302.         *q = bp;
  303.     } else {
  304.         for(p = *q ; p->anext != NULLBUF ; p = p->anext)
  305.             ;
  306.         p->anext = bp;
  307.     }
  308.     restore(i_state);
  309. }
  310. /* Unlink a packet from the head of the queue */
  311. struct mbuf *
  312. dequeue(q)
  313. register struct mbuf **q;
  314. {
  315.     register struct mbuf *bp;
  316.     char i_state;
  317.  
  318.     if(q == NULLBUFP)
  319.         return NULLBUF;
  320.     i_state = disable();
  321.     if((bp = *q) != NULLBUF){
  322.         *q = bp->anext;
  323.         bp->anext = NULLBUF;
  324.     }
  325.     restore(i_state);
  326.     return bp;
  327. }    
  328.  
  329. /* Copy user data into an mbuf */
  330. struct mbuf *
  331. qdata(data,cnt)
  332. char *data;
  333. int16 cnt;
  334. {
  335.     register struct mbuf *bp;
  336.  
  337.     if((bp = alloc_mbuf(cnt)) == NULLBUF)
  338.         return NULLBUF;
  339.     memcpy(bp->data,data,(int)cnt);
  340.     bp->cnt = cnt;
  341.     return bp;
  342. }
  343. /* Copy mbuf data into user buffer */
  344. int16
  345. dqdata(bp,buf,cnt)
  346. struct mbuf *bp;
  347. char *buf;
  348. unsigned cnt;
  349. {
  350.     unsigned n,tot;
  351.     struct mbuf *bp1;
  352.  
  353.     if(buf == NULLCHAR)
  354.         return 0;
  355.     
  356.     tot = 0;
  357.     for(bp1 = bp;bp1 != NULLBUF; bp1 = bp1->next){
  358.         n = min(bp1->cnt,cnt);
  359.         memcpy(buf,bp1->data,(int)n);
  360.         cnt -= n;
  361.         buf += n;
  362.         tot += n;
  363.     }
  364.     free_p(bp);
  365.     return tot;
  366. }
  367. /* Pull a 32-bit integer in host order from buffer in network byte order */
  368. int32
  369. pull32(bpp)
  370. struct mbuf **bpp;
  371. {
  372.     int32 rval;
  373.     char buf[4];
  374.     register char *cp;
  375.  
  376.     if(pullup(bpp,buf,4) != 4){
  377.         /* Return zero if insufficient buffer */
  378.         return 0;
  379.     }
  380.     cp = buf;
  381.  
  382.     /* Unwound for speed */
  383.     rval = uchar(*cp++);
  384.     rval <<= 8;
  385.     rval |= uchar(*cp++);
  386.     rval <<= 8;
  387.     rval |= uchar(*cp++);
  388.     rval <<= 8;
  389.     rval |= uchar(*cp);
  390.  
  391.     return rval;
  392. }
  393. /* Pull a 16-bit integer in host order from buffer in network byte order */
  394. int16
  395. pull16(bpp)
  396. struct mbuf **bpp;
  397. {
  398.     int16 rval;
  399.     char buf[2];
  400.     register char *cp;
  401.  
  402.     if(pullup(bpp,buf,2) != 2){
  403.         /* Return zero if insufficient buffer */
  404.         return 0;
  405.     }
  406.     cp = buf;
  407.  
  408.     rval = uchar(*cp++);
  409.     rval <<= 8;
  410.     rval |= uchar(*cp);
  411.     return rval;
  412. }
  413. /* Pull single character from mbuf */
  414. char
  415. pullchar(bpp)
  416. struct mbuf **bpp;
  417. {
  418.     char c;
  419.  
  420.     if(pullup(bpp,&c,1) != 1)
  421.         /* Return zero if nothing left */
  422.         c = 0;
  423.     return c;
  424. }
  425. /* Put a long in host order into a char array in network order */
  426. char *
  427. put32(cp,x)
  428. register char *cp;
  429. int32 x;
  430. {
  431.     *cp++ = x >> 24;
  432.     *cp++ = x >> 16;
  433.     *cp++ = x >> 8;
  434.     *cp++ = x;
  435.     return cp;
  436. }
  437. /* Put a short in host order into a char array in network order */
  438. char *
  439. put16(cp,x)
  440. register char *cp;
  441. int16 x;
  442. {
  443.     *cp++ = x >> 8;
  444.     *cp++ = x;
  445.  
  446.     return cp;
  447. }
  448.